#include "../include/Event.h"

#include <algorithm>

namespace ZY {

    map<int, vector<Event::CallBack> > EventBase::s_event;
    map<int, vector<EventBase::CallBackOfObject> > EventBase::so_event;

    EventBase::EventBase()
    {
        //ctor
    }

    EventBase::EventBase( const EventBase & eb )
    {
        copyFrom( eb );
    }

    EventBase& EventBase::operator=( const  EventBase & eb )
    {
        return copyFrom( eb );
    }

    EventBase& EventBase::copyFrom( const EventBase & eb )
    {
        if ( this == &eb ) {
            return *this;
        }

        m_event.clear();
        mo_event.clear();

        for( map<int , vector<Event::CallBack> >::const_iterator iter = eb.m_event.begin(); iter != eb.m_event.end() ; iter ++ ) {
            const vector<Event::CallBack> & v = (*iter).second;
            m_event[ (*iter).first ] = v ;
        }

        for( map<int , vector<CallBackOfObject> >::const_iterator iter = eb.mo_event.begin(); iter != eb.mo_event.end() ; iter ++ ) {
            const vector<CallBackOfObject> & v = (*iter).second;
            mo_event[ (*iter).first ]  = v;
        }

        return *this;
    }

    EventBase::~EventBase()
    {
        //dtor

        for( map<int , vector<Event::CallBack> >::iterator iter = m_event.begin(); iter != m_event.end() ; iter ++ ) {
            vector<Event::CallBack> & v = (*iter).second;
            v.clear();
        }
        m_event.clear();
        for( map<int , vector<CallBackOfObject> >::iterator iter = mo_event.begin(); iter != mo_event.end() ; iter ++ ) {
            vector<CallBackOfObject> & v = (*iter).second;
            v.clear();
        }
        mo_event.clear();
    }

    void EventBase::addEventListener( int eventId , Event::CallBack fn )
    {

        vector<Event::CallBack> & v = m_event[ eventId ];
        if ( v.size() > 0 ) {
            vector<Event::CallBack>::iterator iter;
            iter = find( v.begin() , v.end() , fn );
            if ( iter != v.end() ) {
                return;
            }
        }
        v.push_back( fn );
    }

    void EventBase::addEventListener( int eventId , Event::CallBackWithObject fn , void *object )
    {
        vector<CallBackOfObject> & v = mo_event[ eventId ];
        CallBackOfObject cbo;
        cbo.object = object;
        cbo.fn = fn;
        if ( v.size() > 0 ) {
            //vector<CallBackOfObject>::iterator iter;
            for( size_t i = 0 ; i < v.size() ; i ++ ) {
                if ( fn == v[i].fn && object == v[i].object ) {
                    return;
                }
            }

//            iter = find( v.begin() , v.end() , cbo );
//            if ( iter != v.end() ) {
//                return;
//            }
        }
        v.push_back( cbo );
    }

    void EventBase::removeAllEvent()
    {
            mo_event.clear();
            m_event.clear();
    }

    void EventBase::removeAllBasicEvent()
    {
       m_event.clear();
    }

    void EventBase::removeAllObjectEvent()
    {
        mo_event.clear();
    }

    void EventBase::removeEventListener( int eventId , Event::CallBackWithObject fn , void *object )
    {
        if ( mo_event.count( eventId ) > 0 ) {
            vector< CallBackOfObject > & v = mo_event[ eventId ];
            vector< CallBackOfObject >::iterator iter;
            while( true ) {
                if ( iter == v.end() ) {
                    break;
                }
                if ( (*iter).fn == fn && (*iter).object == object ) {
                    iter = v.erase( iter );
                } else {
                    iter ++;
                }
            }
        }

    }



    void EventBase::removeEventListener( int eventId , Event::CallBack fn )
    {
        if ( m_event.count( eventId ) > 0 ) {
            vector<Event::CallBack> & v = m_event[ eventId ];
            vector<Event::CallBack>::iterator iter;
            iter = find( v.begin() , v.end() , fn );
            if ( iter != v.end() ) {
                v.erase( iter );
            }
        }
    }

    void EventBase::removeEventListener( int eventId )
    {
        if ( m_event.count( eventId ) > 0 ) {
            m_event.erase( eventId );
        }
    }
    bool EventBase::callEventListener( int eventId , Event *ev )
    {
        bool ret = false;
        if ( m_event.count( eventId )== 0 && mo_event.count(eventId)==0) {
            return ret;
        }


        {
            vector<Event::CallBack> & v = m_event[ eventId ];
            if ( v.size() > 0 ) {
                for( unsigned int i = 0 ; i < v.size() ; i ++ ) {
                    v[i]( ev );
                }
                ret = true;
            }

        }


        {
            vector<CallBackOfObject> & v = mo_event[ eventId ];
            if ( v.size() > 0 ) {
                for( unsigned int i = 0 ; i < v.size() ; i ++ ) {
                    v[i].fn( v[i].object , ev );
                }
                ret = true;
            }

        }

        return ret;

    }

    void EventBase::addStaticEventListener( int eventId , Event::CallBack fn )
    {

        vector<Event::CallBack> & v = s_event[ eventId ];
        if ( v.size() > 0 ) {
            vector<Event::CallBack>::iterator iter;
            iter = find( v.begin() , v.end() , fn );
            if ( iter != v.end() ) {
                return;
            }
        }
        v.push_back( fn );
    }

    void EventBase::addStaticEventListener( int eventId , Event::CallBackWithObject fn , void *object )
    {
        vector<CallBackOfObject> & v = so_event[ eventId ];
        CallBackOfObject cbo;
        cbo.object = object;
        cbo.fn = fn;
        if ( v.size() > 0 ) {
            for( size_t i = 0 ; i < v.size() ; i ++ ) {
                if ( fn == v[i].fn && object == v[i].object ) {
                    return;
                }
            }
        }
        v.push_back( cbo );
    }

    void EventBase::removeStaticEventListener( int eventId , Event::CallBackWithObject fn , void *object )
    {
        if ( so_event.count( eventId ) > 0 ) {
            vector< CallBackOfObject > & v = so_event[ eventId ];
            vector< CallBackOfObject >::iterator iter = v.begin();
            while( true ) {
                if ( iter == v.end() ) {
                    break;
                }
                if ( (*iter).fn == fn && (*iter).object == object ) {
                    iter = v.erase( iter );
                } else {
                    iter ++;
                }
            }
        }
    }

    void EventBase::removeStaticEventListener( int eventId , Event::CallBack fn )
    {
        if ( s_event.count( eventId ) > 0 ) {
            vector<Event::CallBack> & v = s_event[ eventId ];
            vector<Event::CallBack>::iterator iter;
            iter = find( v.begin() , v.end() , fn );
            if ( iter != v.end() ) {
                v.erase( iter );
            }
        }
    }

    void EventBase::removeStaticEventListener( int eventId )
    {
        if ( s_event.count( eventId ) > 0 ) {
            s_event.erase( eventId );
        }
    }
    bool EventBase::callStaticEventListener( int eventId , Event *ev )
    {
        bool ret = false;
        if ( s_event.count( eventId )== 0 && so_event.count(eventId)==0) {
            return ret;
        }


        {
            vector<Event::CallBack> & v = s_event[ eventId ];
            if ( v.size() > 0 ) {
                for( unsigned int i = 0 ; i < v.size() ; i ++ ) {
                    v[i]( ev );
                }
                ret = true;
            }
        }


        {
            vector<CallBackOfObject> & v = so_event[ eventId ];
            if ( v.size() > 0 ) {
                for( unsigned int i = 0 ; i < v.size() ; i ++ ) {
                    v[i].fn( v[i].object , ev );
                }
                ret = true;
            }
        }

        return ret;

    }

    void Event::assign( Event &ev )
    {
        this->ptr = ev.ptr;
        this->data.copyFrom( ev.data );
    }
}
